package com.bocloud.cmp.service.app.resource;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.bocloud.cmp.entity.app.resource.Layout;
import com.bocloud.cmp.entity.resource.Cluster;
import com.bocloud.cmp.interfaces.app.resource.LayoutService;
import com.bocloud.cmp.service.utils.FileUtil;
import com.bocloud.common.enums.BaseStatus;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestUser;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.DateTools;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.coordinator.harmony.HarmonyLock;
import com.bocloud.coordinator.harmony.LockFactory;
import com.bocloud.soc.entity.User;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service("layoutService")
public class LayoutServiceImpl extends CommonServiceImpl implements LayoutService {

	private static final Logger logger = LoggerFactory.getLogger(LayoutServiceImpl.class);

	@Autowired
	private LockFactory lockFactory;

	@Value("${local.storage.path}")
	private String localStoragePath;

	@Override
	public BsmResult list(int page, int rows, List<Param> params, Map<String, String> sorter, Boolean simple,
			RequestUser user) {
		GridBean gridBean = null;
		BsmResult bsmResult = new BsmResult();
		if (null == params) {
			params = Lists.newArrayList();
		}
		if (null == sorter) {
			sorter = Maps.newHashMap();
		}
		sorter.put("gmtCreate", Common.ONE);
		try {
			int total = layoutDao.count(params);
			if (simple) {
				List<SimpleBean> beans = layoutDao.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<Layout> layouts = layoutDao.list(page, rows, params, sorter);
				if (layouts != null && !layouts.isEmpty()) {
					for (Layout layout : layouts) {
						// 获取用户信息
						User creator = userDao.query(layout.getCreaterId());
						layout.setCreatorName(creator.getName());
						// 获取修改者信息
						User mender = userDao.query(layout.getMenderId());
						layout.setMenderName(mender.getName());
					}
				}
				gridBean = GridHelper.getBean(page, rows, total, layouts);
			}
			bsmResult.setSuccess(true);
			bsmResult.setData(gridBean);
			bsmResult.setMessage("获取编排信息成功！");
		} catch (Exception e) {
			bsmResult.setSuccess(false);
			logger.error("Query cluster list Exception:", e);
			bsmResult.setMessage("获取编排信息失败！");
		}
		saveLog("layout/operation", "编排列表查询", bsmResult.getMessage(), user.getId());
		return bsmResult;
	}

	@Override
	public BsmResult listByAppId(Long appId, int page, int rows, List<Param> params, Map<String, String> sorter,
			Boolean simple, RequestUser user) {
		GridBean gridBean = null;
		BsmResult bsmResult = new BsmResult();
		if (null == params) {
			params = Lists.newArrayList();
		}
		if (null == sorter) {
			sorter = Maps.newHashMap();
		}
		sorter.put("gmtCreate", Common.ONE);
		try {
			int total = layoutDao.countByAppId(appId, params);
			if (simple) {
				List<SimpleBean> beans = layoutDao.listByAppId(appId, params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<Layout> layouts = layoutDao.listByAppId(appId, page, rows, params, sorter);
				if (layouts != null && !layouts.isEmpty()) {
					for (Layout layout : layouts) {
						// 获取用户信息
						User creator = userDao.query(layout.getCreaterId());
						layout.setCreatorName(creator.getName());
						// 获取修改者信息
						User mender = userDao.query(layout.getMenderId());
						layout.setMenderName(mender.getName());
					}
				}
				gridBean = GridHelper.getBean(page, rows, total, layouts);
			}
			bsmResult.setSuccess(true);
			bsmResult.setData(gridBean);
			bsmResult.setMessage("获取应用依赖的编排文件信息成功！");
		} catch (Exception e) {
			logger.error("Query cluster list fail:", e);
			bsmResult.setSuccess(false);
			bsmResult.setMessage("获取应用依赖的编排文件信息失败！");
		}
		saveLog("layout/operation", "获取应用依赖的编排文件", bsmResult.getMessage(), user.getId());
		return bsmResult;
	}

	@Override
	public BsmResult create(Layout layout, RequestUser user) {
		BsmResult bsmResult = new BsmResult();
		String fileDir;
		try {
			String fileName;
			// 名称校验
			Layout checkResult = layoutDao.checkName(layout.getName());
			if (null != checkResult) {
				bsmResult.setMessage("编排名称已经存在");
				saveLog("layout/operation", "编排文件创建", bsmResult.getMessage(), user.getId());
				return bsmResult;
			}
			fileDir = localStoragePath + File.separatorChar
					+ DateTools.formatTime2String(new Date(), "yyyyMMddHHmmssSSS") + "-" + layout.getName();
			if ("".equals(layout.getFileName())) {
				fileName = fileDir + File.separatorChar + layout.getName() + ".yaml";
				layout.setFileName(layout.getName() + ".yaml");
			} else {
				fileName = fileDir + File.separatorChar + layout.getFileName();
			}
			bsmResult = FileUtil.createFile(fileName, layout.getFileContent());
		} catch (Exception e) {
			logger.error("file upload failed", e);
			bsmResult.setSuccess(false);
			bsmResult.setMessage("上传文件异常！");
			saveLog("layout/operation", "编排文件创建", bsmResult.getMessage(), user.getId());
			return bsmResult;
		}
		if (bsmResult.isSuccess()) {
			layout.setStatus(BaseStatus.NORMAL.name());
			layout.setFilePath(fileDir);
			layout.setProps(String.valueOf(1));
			try {
				layoutDao.save(layout);
				bsmResult.setSuccess(true);
				bsmResult.setData(layout);
				bsmResult.setMessage("添加编排文件成功！");
			} catch (Exception e) {
				logger.error("layout file save failed", e);
				bsmResult.setSuccess(false);
				bsmResult.setMessage("添加编排文件失败！");
			}
		} else {
			bsmResult.setSuccess(false);
			bsmResult.setMessage("上传文件异常！");
		}
		saveLog("layout/operation", "编排文件创建", bsmResult.getMessage(), user.getId());
		return bsmResult;
	}

	@Override
	public BsmResult modify(Layout bean, Long userId) {
		BsmResult bsmResult = new BsmResult();
		String path = Layout.class.getSimpleName() + "_" + bean.getId();
		HarmonyLock lock = null;
		lock = lockFactory.getLock(path);
		if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
			logger.warn("Get harmonyLock time out!");
			bsmResult.setMessage("访问编排文件超时！");
			saveLog("layout/operation", "修改编排文件信息", bsmResult.getMessage(), userId);
			return bsmResult;
		}
		try {
			Layout layout = layoutDao.query(bean.getId());
			if (null == layout) {
				logger.warn("Layout does not exist!");
				bsmResult.setMessage("编排文件不存在！");
				saveLog("layout/operation", "修改编排文件信息", bsmResult.getMessage(), userId);
				return bsmResult;
			}
			if (bean.getFileContent() != null) {
				bsmResult = FileUtil.createFile(layout.getFilePath() + File.separatorChar + layout.getFileName(),
						bean.getFileContent());
			}
			if (bsmResult.isSuccess()) {
				layout.setName(bean.getName());
				layout.setFileName(layout.getFileName());
				layout.setRemark(bean.getRemark());
				layout.setProps(bean.getProps());
				layout.setMenderId(userId);
				this.layoutDao.update(layout);
			}
			bsmResult.setSuccess(true);
			bsmResult.setMessage("编排文件修改成功！");
		} catch (Exception e) {
			bsmResult.setSuccess(false);
			logger.error("Modify cluster exception:", e);
			bsmResult.setMessage("编排文件修改失败！");
		} finally {
			lock.release();
		}
		saveLog("layout/operation", "修改编排文件信息", bsmResult.getMessage(), userId);
		return bsmResult;
	}

	@Override
	public BsmResult remove(Long id, Long userId) {
		BsmResult bsmResult = new BsmResult();
		String path = Cluster.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				bsmResult.setMessage("访问编排文件超时！");
				saveLog("layout/operation", "删除编排文件", bsmResult.getMessage(), userId);
				return bsmResult;
			}
			Layout object = layoutDao.query(id);
			if (null == object) {
				logger.warn("Layout does not exist!");
				bsmResult.setMessage("编排文件不存在！");
				saveLog("layout/operation", "删除编排文件", bsmResult.getMessage(), userId);
				return bsmResult;
			}
			if (!removeLayoutInfos(id, userId)) {
				bsmResult.setMessage("编排文件删除异常！");
				saveLog("layout/operation", "删除编排文件", bsmResult.getMessage(), userId);
				return bsmResult;
			}
			bsmResult.setSuccess(true);
			bsmResult.setMessage("编排文件删除成功！");
			saveLog("layout/operation", "删除编排文件", bsmResult.getMessage(), userId);
			return bsmResult;
		} catch (Exception e) {
			logger.error("Remove cluster exception:", e);
			bsmResult.setMessage("编排文件删除失败！");
			saveLog("layout/operation", "删除编排文件", bsmResult.getMessage(), userId);
			return bsmResult;
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult detail(Long id, RequestUser user) {
		BsmResult bsmResult = new BsmResult();
		try {
			Layout layout = layoutDao.query(id);
			if (null == layout) {
				bsmResult.setMessage("编排文件不存在！");
				return bsmResult;
			}
			// 获取用户信息
			User creator = userDao.query(layout.getCreaterId());
			layout.setCreatorName(creator.getName());
			// 获取修改者信息
			User mender = userDao.query(layout.getMenderId());
			layout.setMenderName(mender.getName());
			bsmResult = FileUtil.readFile(layout.getFilePath() + File.separatorChar + layout.getFileName());
			if (bsmResult.isSuccess()) {
				layout.setFileContent(bsmResult.getData().toString());
				bsmResult.setSuccess(true);
				bsmResult.setMessage("获取编排文件信息成功！");
				bsmResult.setData(layout);
			} else {
				bsmResult.setMessage("读取编排文件信息失败！");
			}
		} catch (Exception e) {
			logger.error("Get cluster exception：", e);
			bsmResult.setSuccess(false);
			bsmResult.setMessage("获取编排文件信息失败！");
		} finally {
			saveLog("layout/operation", "编排文件详情", bsmResult.getMessage(), user.getId());
		}
		return bsmResult;
	}

	private boolean removeLayoutInfos(Long id, Long userId) {
		try {

			return layoutDao.remove(id, userId) && layoutDao.deleteLayoutAppInfo(id);
		} catch (Exception e) {
			logger.error("Remove layout infos Excetion", e);
			return false;
		}
	}

}
